﻿#region Copyright 2011 Mike Goatly
// This source is subject to the the MIT License (MIT)
// All rights reserved.
#endregion

#if DEBUG && !NETFX_CORE
namespace Lifti
{
    #region Using Statements
    using System;
    using System.Globalization;
    using System.Linq;
    using System.Reflection;
    using System.Windows.Forms;
    using Microsoft.VisualStudio.DebuggerVisualizers;
    #endregion

    /// <summary>
    /// A Visualizer for the FullTextIndex class.
    /// </summary>
    public class FullTextIndexVisualizer : DialogDebuggerVisualizer
    {
        #region Private Variables
        /// <summary>
        /// The <see cref="T:Microsoft.VisualStudio.DebuggerVisualizers.IDialogVisualizerService"/> object for this instance.
        /// </summary>
        private IDialogVisualizerService service; 
        #endregion

        #region Protected Methods
        /// <summary>
        /// Shows the visualizer.
        /// </summary>
        /// <param name="windowService">An object of type <see cref="T:Microsoft.VisualStudio.DebuggerVisualizers.IDialogVisualizerService"/>, which provides methods your visualizer can use to display Windows forms, controls, and dialogs.</param>
        /// <param name="objectProvider">An object of type <see cref="T:Microsoft.VisualStudio.DebuggerVisualizers.IVisualizerObjectProvider"/>. This object provides communication from the debugger side of the visualizer to the object source (<see cref="T:Microsoft.VisualStudio.DebuggerVisualizers.VisualizerObjectSource"/>) on the debuggee side.</param>
        protected override void Show(IDialogVisualizerService windowService, IVisualizerObjectProvider objectProvider)
        {
            this.service = windowService;

            object rawData = objectProvider.GetObject();
            var objectType = rawData.GetType();
            var method = this.GetType().GetMethod("ShowIndexer", BindingFlags.Instance | BindingFlags.NonPublic);
            method = method.MakeGenericMethod(objectType.GetGenericArguments());
            method.Invoke(this, new object[] { rawData });
        } 
        #endregion

        #region Private Methods
        /// <summary>
        /// Shows the indexer for the given type of item.
        /// </summary>
        /// <typeparam name="TItem">The type of the item associated to the indexer.</typeparam>
        /// <param name="indexer">The indexer to show.</param>
        private void ShowIndexer<TItem>(FullTextIndex<TItem> indexer)
        {
            using (Form displayForm = new Form())
            {
                TreeView tree = new TreeView();
                tree.Dock = DockStyle.Fill;
                displayForm.Controls.Add(tree);

                AddNode(indexer.RootNode, tree.Nodes);

                this.service.ShowDialog(displayForm);
            }
        }

        /// <summary>
        /// Adds a node to the tree.
        /// </summary>
        /// <typeparam name="TItem">The type of the item.</typeparam>
        /// <param name="node">The node to add the tree node for.</param>
        /// <param name="nodes">The nodes collection to add the new node to.</param>
        private void AddNode<TItem>(IndexNode<TItem> node, TreeNodeCollection nodes)
        {
            if (node == null)
            {
                return;
            }

            TreeNode treeNode;
            var childNodes = node.GetChildNodes();
            if (childNodes != null)
            {
                foreach (var childNode in childNodes)
                {
                    treeNode = new TreeNode(String.Format(CultureInfo.InvariantCulture, "{0} items:{1}", childNode.IndexedCharacter, childNode.GetDirectAndChildItems().Count()));
                    nodes.Add(treeNode);
                    AddNode(childNode, treeNode.Nodes);
                }
            }
        } 
        #endregion
    }
}
#endif